#include "ConflictAnalysis/CUDAListGraphTester.cuh"
#include "ConflictAnalysis/ConflictAnalyzerGenericTester.cuh"
#include "../SATSolver/DataToDevice.cuh"
#include "Tester.cuh"
#include "../FileManager/FormulaData.cuh"
#include "../FileManager/Lex_byacc/cnf_reader.cuh"
#include <vector>
#include "../SATSolver/SolverTypes.cuh"
#include "../FileManager/FileUtils.cuh"
#include "../Utils/GPUStaticVec.cuh"
#include "../SATSolver/VariablesStateHandler.cuh"
#include "SATSolver/BacktrackerTester.cuh"
#include "BCPStrategy/WatchedClausesListTester.cuh"
#include "Statistics/RuntimeStatisticsTester.cuh"
#include "ConflictAnalysis/ConflictAnalyzerWithWatchedLitsTester.cuh"
#include "ClauseLearning/LearntClausesManagerTester.cuh"
#include "Utils/NodesRepositoryTester.cuh"
#include "Utils/GPULinkedListTester.cuh"




__global__ void unit_test_two_watched_conflict_analyzer(DataToDevice data,int file_number)
{
	ConflictAnalyzerWithWatchedLitsTester cawwlt(data, file_number);

	cawwlt.test_all();

	int errors = cawwlt.get_number_of_errors();
	int total = cawwlt.get_number_of_tests();

	printf("\nSummary:\nThere were %d errors out of %d total tests.\n", errors, total);

}

__global__ void unit_test_kernel(DataToDevice data)
{
	//data.get_clauses_db().print_all();

	GPUVec<Var> dead_vars = data.get_dead_vars();
	CUDAListGraphTester graph_tester(data);
	VariablesStateHandler handler(data.get_number_of_variables(), dead_vars, NULL);
	BacktrackerTester backtracker_tester(data);
	WatchedClausesListTester watched_clauses_tester(data);
	LearntClausesManagerTester learnt_clauses_manager_tester(data);
	RuntimeStatisticsTester statistics_tester(data);
	NodesRepositoryTester nodes_repository_tester(data);
	GPULinkedListTester linked_list_tester;

	GPUStaticVec<Tester*, MAX_TESTERS> testers;

	/*
	testers.add(&graph_tester);
	testers.add(&backtracker_tester);
	testers.add(&watched_clauses_tester);
	testers.add(&statistics_tester);
	testers.add(&learnt_clauses_manager_tester);
	testers.add(&nodes_repository_tester);
	*/

	testers.add(&linked_list_tester);

	int errors = 0;
	int total = 0;

	for(int i = 0; i < testers.size_of(); i++)
	{
		Tester * tester = testers.get(i);
		tester->test_all();

		errors += tester->get_number_of_errors();
		total += tester->get_number_of_tests();
	}

	printf("\nSummary:\nThere were %d errors out of %d total tests.\n", errors, total);

}

DataToDevice read_input(char* file)
{
	int lines = number_of_lines(file);
	FormulaData data(lines, true);

	read_cnf(file, data);

	std::vector<Lit> * set_lits = data.get_set_literals();

	GPUVec<Var> dead_vars(set_lits->size());

	for(std::vector<Lit>::iterator iter = set_lits->begin();
			iter < set_lits->end(); ++iter)
	{
		dead_vars.add(var(*iter));
	}

	DataToDevice data_to_device(data.get_formula_dev(),
			data.get_number_of_variables(),
			data.get_number_of_clauses(), 1, 1, 1, data.get_largest_clause_size(),
			dead_vars);

	return data_to_device;
}

void test_file(char* file)
{
	DataToDevice data_to_device = read_input(file);
	unit_test_kernel<<<1,1>>>(data_to_device);

}

int main_unit(int argc, char** argv)
{

	if(argc < 2)
	{
		printf("Wrong number of parameters\n");
		exit(2);
	}

	if(argv[1][0] == '1')
	{
		printf("File = %s\n", argv[2]);
		test_file(argv[2]);
		cudaThreadSynchronize();
	}
	if(argv[1][0] == '2')
	{
		if(argc != 4)
		{
			printf("Wrong number of parameters\n");
			exit(2);
		}

		char* two_watched_test_file1 = argv[2];
		DataToDevice data_f1 = read_input(two_watched_test_file1);
		unit_test_two_watched_conflict_analyzer<<<1,1>>>(data_f1, atoi(argv[3]));
		cudaDeviceReset();
	}

	/*
	for(int i = 1; i < argc; i++)
	{
		test_file(argv[i]);
		cudaThreadSynchronize();
	}



	char* two_watched_test_file1 =
			"/home/jaime/GPUSATSolver/tests/unit_tests_inputs/ConflictAnalyzerWithWatchedListTester_file1.cnf";

	DataToDevice data_f1 = read_input(two_watched_test_file1);



	char* two_watched_test_file2 =
				"/home/jaime/GPUSATSolver/tests/unit_tests_inputs/ConflictAnalyzerWithWatchedListTester_file2.cnf";

	DataToDevice data_f2 = read_input(two_watched_test_file2);


	unit_test_two_watched_conflict_analyzer<<<1,1>>>(data_f2, 2);

	cudaDeviceReset();
	*/
}
